package tools.settings.xml;

import java.util.*;

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import tools.settings.SettingsReaderException;

/**
 * Remark: elements are only processed one-level done (so two-level down elements
 * will be handled as one-level elements, in other words only the <b>local</b>
 * names of the elements are used.
 *
 * Remark2: all the attributes of the xml elements are added as paramters to
 * the element.
 *
 * @author Lynne Vandousselaere
 */
public class SimpleSAXHandler extends DefaultHandler {

    /* A map containing all XML elements, with key=name of the element,
     * and value= a list of parameters as (name,value)-sets.
     * v1: parameternames used are "xmlns", "type", "qname" and "value".
     */
    private Map<String, Map<String, String>> elements;
    private boolean endElement = true;
    private Map<String, String> currPars;
    private ArrayList<String> errors;

    public SimpleSAXHandler() {
        super();
    }

    /**
     * Check the handler if any user defined errors have occured, if so,
     * throw a fetchException.
     */
    public void checkErrors() throws SettingsReaderException {
        if (!errors.isEmpty())
            throw new SettingsReaderException("The following elements are declared " +
                    "twice in the XML file : " + errors);
    }

    /**
     * Get the elements that have been parsed, or "null" if nothing has been
     * parsed.
     *
     * @return
     */
    public Map<String, Map<String, String>> getElements() {
        return elements;
    }


    ////////////////////////////////////////////////////////////////////
    // Event handlers.
    ////////////////////////////////////////////////////////////////////
    @Override
    public void startDocument() {
        elements = new HashMap<String, Map<String, String>>();
        errors = new ArrayList<String>();
    }

    @Override
    public void endDocument() {
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) {
        endElement = false;

        /* Extract all necessary attributes here!
         */
        currPars = new HashMap<String, String>();
        currPars.put("xmlns", uri);
        currPars.put("qname", qName);
        for(int i = 0; i < atts.getLength(); i++)
            currPars.put(atts.getLocalName(i), atts.getValue(i));
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        if (elements.put(localName.toLowerCase(), currPars) != null)
            errors.add(localName.toLowerCase());

        endElement = true;
    }

    @Override
    public void characters(char ch[], int start, int length) {
        if (!endElement)
            currPars.put("value", new String(ch, start, length));
    }
}

